package juc;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

class MyBroker{
    //开启生产消费/关闭生产消费 标记位，内存可见性保证各个线程立刻感知当前状态
    private volatile Boolean flag = true;
    //资源
    private AtomicInteger mianbao = new AtomicInteger();
    //阻塞队列的类型（可以理解为货架）
    BlockingQueue<String> queue = null;
    //构造面包店的构造方法
    public MyBroker(BlockingQueue<String> queue) {
        this.queue = queue;
    }
    //生产面包
    public void productMianBao() throws Exception{
        String data = null;
        Boolean result;
        while (flag){
            //生产中...面包编号+1 转为字符串 付给一个data，放入队列
            //可以理解为，生产了1个面包，取名为i+1，放到货架中供消费
           data = mianbao.incrementAndGet()+"";
           //货架满了就等一会，最多等2S
           result = queue.offer(data,2L, TimeUnit.SECONDS);
           if (result){
               System.out.println(Thread.currentThread().getName()+" 面包 "+data+" 放入货架成功");
           }else {
               System.out.println(Thread.currentThread().getName()+" 面包 "+data+" 放入货架失败");
           }
           //人为干预：1S生产一个
           TimeUnit.SECONDS.sleep(1);
        }
        //停止生产
        System.out.println(Thread.currentThread().getName()+" 停止生产面包");
    }

    //出售面包
    public void consumeMianBao() throws Exception{
        String data = null;
        while (flag){
            //从货架拿面包卖掉，如果货架没有，最多等2S
            data = queue.poll(2L,TimeUnit.SECONDS);
            //如果本次出售面包失败，说明生产面包的不生产了，说明关门了（ 当然，也可以有别的逻辑）
            if (data==null || data.equalsIgnoreCase("")){
                flag = false;
                System.out.println(Thread.currentThread().getName()+" 没买到面包");
                return;
            }
            System.out.println(Thread.currentThread().getName()+" 购买了 "+data);
        }
    }

    //停止营业
    public void stop(){
        flag = false;
    }
}

public class ProductorAdnConsumer2 {
    public static void main(String[] args) throws InterruptedException {
        //面包店,货架最多可以放3个面包
        MyBroker broker = new MyBroker(new ArrayBlockingQueue<String>(3));

        //生产面包
        new Thread(()->{
            System.out.println("面包店开门.....");
            try {
                broker.productMianBao();
            } catch (Exception e) {
                e.printStackTrace();
            }
        },"面包师").start();

        //出售/购买面包
        new Thread(()->{
            try {
                broker.consumeMianBao();
            } catch (Exception e) {
                e.printStackTrace();
            }
            System.out.println("面包店关门.....");
        },"消费者").start();

        //模拟一天时间
        TimeUnit.SECONDS.sleep(10);
        //关门
        broker.stop();

    }
}
